package com.woniuxy.rabbit.config;

import com.alibaba.fastjson2.JSON;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;

import javax.annotation.PostConstruct;

/**
 * @author     ：hy zhu
 * @date       ：Created in 2025/6/6 15:52
 * @description：TODO 消息的可靠投递
 * @modified By：
 * @version: 1, 0
 */
@Slf4j
@Configuration
public class CallbackConfig implements RabbitTemplate.ConfirmCallback, RabbitTemplate.ReturnCallback {

    @Autowired
    private RabbitTemplate rabbitTemplate;


    /**
     * 初始化回调函数
     */
    @PostConstruct
    public void init() {
        rabbitTemplate.setConfirmCallback(this);
        rabbitTemplate.setReturnCallback(this);
        rabbitTemplate.setMandatory(true);
    }

    /**
     * 确认消息是否被发送
     * 前提条件：配置项设置：spring.rabbitmq.publisher-confirms=true
     * 不管是发送成功还是失败，都会执行该方法
     *
     * @param correlationData
     * @param b
     * @param s
     */
    @Override
    public void confirm(CorrelationData correlationData, boolean b, String s) {
        log.info("消息发送成功：correlationData={},ack={},cause={}", correlationData, b, s);
        if (b) return;

        //  TODO 添加消息发送失败处理逻辑
        // 1、重发消息（次数的上限，如：10；每次消息发送的间隔，如：本次间隔 = 上次间隔 * 2 ）  消息体，交换机名称，路由键

        byte[] body = correlationData.getReturnedMessage().getBody();
        String exchange = correlationData.getReturnedMessage().getMessageProperties().getReceivedExchange();
        String routingKey = correlationData.getReturnedMessage().getMessageProperties().getReceivedRoutingKey();
        log.info("confirm 消息发送失败：message={},exchange={},routingKey={}", JSON.parseObject(body, String.class), exchange, routingKey);

        // 2、记录日志
        // 3、持久化消息
        // 4、发送邮件 && 短信 && 人工处理
    }

    /**
     * 消息发送失败回调函数
     * 前提条件：配置项设置：spring.rabbitmq.publisher-returns=true
     * 仅发送失败时执行
     * @param message
     * @param i
     * @param s
     * @param s1
     * @param s2
     */
    @Override
    public void returnedMessage(Message message, int i, String s, String s1, String s2) {
        log.error("消息发送失败：message={},replyCode={},replyText={},exchange={},routingKey={}", message, i, s, s1, s2);
    }
}
